#include <string.h>
#include "jApi.h"

extern "C" void jApiInit(void);
extern "C"
{
	#include "settings_manager.h"
}

extern "C" int set_video_fmt_2_json(int value);
extern "C" int set_video_bitrate_2_json(int value);
extern "C" int set_video_gdrmode_2_json(int value);
extern "C" int set_video_gop_2_json(int value);
extern "C" int set_video_mode_2_json(int value);
extern "C" int set_video_framerate_2_json(int value);
extern "C" int set_video_height_2_json(int value);
extern "C" int set_video_width_2_json(int value);
extern "C" int set_audioswitch_2_json(int value);
static jApi_t *jApi = nullptr;

void jApiInit(void)
{
	int i = 0;
    jApi = new jApi_t();
	jApi->json_params_init();
    //printf( "GET ALL INFO IS:%s \n", jApi->getAllInfo() );
    //jApi->printCodecInfo(0);
    //jApi->setCodecRate(0, 800);
    //jApi->setCodecRate(0, 1000);
	//jApi->getAllInfo();
	//int value = 900;
	//jApi->set_json_codec_param_setting(jApi->Json_bitare, 0, (void *)&value);
	//sleep(2);
	//value = 2000;
	//jApi->set_json_codec_param_setting(jApi->Json_bitare, 0, (void *)&value);

	//jApi->set_json_codec_param_setting(jApi->Json_fmt, 0, (void *)"NV16");
}

// ----------------------------------------------------------------
jApi_t::jApi_t()
{
    updSocket = new udpSocket_t(65532);
    updSocket->setDataRevCB(udpRev, this);
}

void jApi_t::sendCmd_noblock(QJsonObject msg)
{
    QByteArray data;
    QJsonDocument doc(msg);

    msgMut.lock();
    newMsgIn = false;
    msgMut.unlock();

    data = doc.toJson(QJsonDocument::Compact);
    updSocket->sendData("127.0.0.1", 8120, data.data(), data.length());
    qDebug() << "( jSendJsonMsg )" << msg;
}

void jApi_t::udpRev(struct in_addr addr, uint16_t port, void *buff, int len, void *dev)
{
    if (nullptr == dev)
        return;
    jApi_t *pThis = static_cast<jApi_t *>(dev);

    QByteArray datagram((char *)buff, len); // 将接收到的数据转换为 QByteArray

    QJsonParseError error;
    QJsonObject jsonObject;

    QJsonDocument json = QJsonDocument::fromJson(datagram, &error); // 对UDP数据 转为 JSON DOM
    if (error.error == QJsonParseError::NoError)
    {
        if (json.isObject()) // 数据为 JSON obj类型，  当前指令也只有OBJ类
        {
            jsonObject = json.object();

            pThis->msgMut.lock();
            pThis->newMsgIn = true;
            pThis->lastMsg = jsonObject;
            //qDebug() << "CMD REV:" << jsonObject;
            pThis->msgMut.unlock();
        }
    }
    else
    {
        // 收到的不是JSON数据
        qDebug() << "错误的socket 数据:" << datagram;
        qDebug() << error.errorString().toUtf8().constData();
        return;
    }
}

QJsonObject jApi_t::sendCmd(QJsonObject cmd)
{
    sendCmd_noblock(cmd);
    return getLastMsg(1);
}

QJsonObject jApi_t::getLastMsg(int blockMode)
{
    QJsonObject ret;

    if (0 == blockMode)
    {
        msgMut.lock();
        if (newMsgIn)
            ret = lastMsg;
        msgMut.unlock();

        return ret;
    }

    for (int i = 0; i < 500; i++)
    {
        msgMut.lock();
        if (newMsgIn)
        {
            ret = lastMsg;
            msgMut.unlock();
            return ret;
        }

        msgMut.unlock();
        usleep(1 * 1000);
    }
    return ret;
}

const char *jApi_t::jsonToString(QJsonObject obj)
{
    QByteArray json;
    QJsonDocument doc(obj);

    qDebug() << obj;

    json = doc.toJson(QJsonDocument::Compact);

    return json.data();
}

QJsonObject jApi_t::stringToJson(const char *buf, int strlen)
{
    QJsonObject emptyObj;
    QByteArray datagram(buf, strlen);

    QJsonParseError error;
    QJsonObject jsonObject;

    QJsonDocument json = QJsonDocument::fromJson(datagram, &error);
    if (error.error == QJsonParseError::NoError)
    {
        if (json.isObject())
        {
            return json.object();
        }
    }
    else
    {
        // 收到的不是JSON数据
        qDebug() << "not a json string:" << datagram;
        qDebug() << error.errorString().toUtf8().constData();
    }

    return emptyObj;
}

const char *jApi_t::getAllInfo()
{
    QJsonObject cmd, ret;

    cmd.insert("cmd", "getall");
    ret = jApi->sendCmd(cmd);

    return jsonToString(ret);
}


//------------params setting interfacec-----------
int jApi_t::json_params_init()
{
	int i = 0;
	QJsonObject cmd, ret;
	cmd.insert("cmd", "getCodec");
	cmd.insert("id", 0);
	ret = jApi->sendCmd(cmd);
	QJsonArray codecList = ret.value("codecList").toArray(); // 从JSON中取 JSON数组方式
	if (0 >= codecList.count())
	{
		printf("Error: can't find codec! \n");
		return -1;
	}
	QJsonObject codecCfg = codecList.at(0).toObject(); // 从JSON数组中取其中一个元素
	int codecId = codecCfg.value("id").toInt(-1);                     // JSON 成员转 INT, 如果"id"这个成员不存在或不是int类型会失败，就按-1返回

	set_decoder_bitrate_setting(codecCfg.value("bitRate").toInt(-1));

	if (strcmp("NV12", codecCfg.value("fmt").toString().toStdString().data()) == 0)
	{
		set_video_fmt_setting(fmt_value_nv12);
	}
	else if (strcmp("NV16", codecCfg.value("fmt").toString().toStdString().data()) == 0)
	{
		set_video_fmt_setting(fmt_value_nv16);
	}
	else if (strcmp("XV20", codecCfg.value("fmt").toString().toStdString().data()) == 0)
	{
		set_video_fmt_setting(fmt_value_xv20);
	}
	else
		set_video_fmt_setting(fmt_value_nv12);


	if (codecCfg.value("gdrMode").toBool())
		set_video_gdrmode_setting(gdrmode_true);
	else
	{
		set_video_gdrmode_setting(gdrmode_false);
	}

	set_video_gop_setting(codecCfg.value("gop").toInt(-1));

	if (strcmp("H264", codecCfg.value("mode").toString().toStdString().data()) == 0)
	{
		set_video_mode_setting(mode_h264);
	}
	else if (strcmp("H265", codecCfg.value("mode").toString().toStdString().data()) == 0)
	{
		set_video_mode_setting(mode_h265);
	}
	else
		set_video_mode_setting(mode_h264);

	set_video_framerate_setting(codecCfg.value("videoFramerate").toInt(-1));

	set_video_height_setting(codecCfg.value("videoHeight").toInt(-1));

	set_video_width_setting(codecCfg.value("videoWidth").toInt(-1));

	return 0;
}

int jApi_t::set_json_codec_param_setting(JsonparamIndex index,int id, void *val)
{
	QJsonObject cmd, ret;

	cmd.insert("cmd", "setCodec");
	cmd.insert("id", id);
	switch (index)
	{
	case Json_bitare:
		cmd.insert("bitRate", *(int *)val);
		break;
	case Json_fmt:
		cmd.insert("fmt", (char *)val);
		break;
	case Json_gdrmode:
		cmd.insert("gdrMode", *(bool *)val);
		break;
	case Json_gop:
		cmd.insert("gop", *(int *)val);
		break;
	case Json_vcu_mode:
		cmd.insert("mode", (char *)val);
		break;
	case Json_framerate:
		cmd.insert("videoFramerate", *(int *)val);
		break;
	case Json_videoHeight:
		cmd.insert("videoHeight", *(int *)val);
		break;
	case Json_videoWidth:
		cmd.insert("videoWidth", *(int *)val);
		break;
	default:
		break;
	}
	ret = jApi->sendCmd(cmd);

	std::string tmpStr = ret.value("result").toString().toStdString();

	if ("success" != tmpStr)
		return -1;
	else
		return 0;
}


int jApi_t::get_json_codec_param_setting(JsonparamIndex index,int id)
{
	QJsonObject cmd, ret;
	cmd.insert("cmd", "getCodec");
	cmd.insert("id", id);
	ret = jApi->sendCmd(cmd);
	QJsonArray codecList = ret.value("codecList").toArray(); // 从JSON中取 JSON数组方式
	if (0 >= codecList.count())
	{
		printf("Error: can't find codec! \n");
		return -1;
	}
	QJsonObject codecCfg = codecList.at(0).toObject(); // 从JSON数组中取其中一个元素
	int codecId = codecCfg.value("id").toInt(-1);                     // JSON 成员转 INT, 如果"id"这个成员不存在或不是int类型会失败，就按-1返回
	switch (index)
	{
	case Json_bitare:
		set_decoder_bitrate_setting(codecCfg.value("bitRate").toInt(-1));
		break;
	case Json_fmt:
		if (strcmp("NV12", codecCfg.value("fmt").toString().toStdString().data()) == 0)
		{
			set_video_fmt_setting(fmt_value_nv12);
		}
		else if (strcmp("NV16", codecCfg.value("fmt").toString().toStdString().data()) == 0)
		{
			set_video_fmt_setting(fmt_value_nv16);
		}
		else if (strcmp("XV20", codecCfg.value("fmt").toString().toStdString().data()) == 0)
		{
			set_video_fmt_setting(fmt_value_xv20);
		}
		else
			set_video_fmt_setting(fmt_value_nv12);
		break;
	case Json_gdrmode:
		if (codecCfg.value("gdrMode").toBool())
			set_video_gdrmode_setting(gdrmode_true);
		else
		{
			set_video_gdrmode_setting(gdrmode_false);
		}
		break;
	case Json_gop:
		set_video_gop_setting(codecCfg.value("gop").toInt(-1));
		break;
	case Json_vcu_mode:
		if (strcmp("H264", codecCfg.value("mode").toString().toStdString().data()) == 0)
		{
			set_video_mode_setting(mode_h264);
		}
		else if (strcmp("H265", codecCfg.value("mode").toString().toStdString().data()) == 0)
		{
			set_video_mode_setting(mode_h265);
		}
		else
			set_video_mode_setting(mode_h264);
		break;
	case Json_framerate:
		set_video_framerate_setting(codecCfg.value("videoFramerate").toInt(-1));
		break;
	case Json_videoHeight:
		set_video_height_setting(codecCfg.value("videoHeight").toInt(-1));
		break;
	case Json_videoWidth:
		set_video_width_setting(codecCfg.value("videoWidth").toInt(-1));
		break;
	default:
		break;
	}
	//int rate = codecCfg.value("bitRate").toInt(-1);
	//std::string fmt = codecCfg.value("fmt").toString().toStdString(); // JSON成员转 STD：：STRING,如果"fmt"这个成员不存在会失败，就按"XV20"返回
	//bool gdrMode = codecCfg.value("gdrMode").toBool();                    // JSON 成员转 BOOL
	return 0;
}

int set_video_bitrate_2_json(int value)
{
	jApi->set_json_codec_param_setting(jApi->Json_bitare, 0, (void *)&value);
	set_decoder_bitrate_setting(value);
	return 0;
}

int set_video_fmt_2_json(int value)
{
	if (value == fmt_value_nv12)
	{
		jApi->set_json_codec_param_setting(jApi->Json_fmt, 0, (void *)"NV12");
	}
	else if(value == fmt_value_nv16)
	{
		jApi->set_json_codec_param_setting(jApi->Json_fmt, 0, (void *)"NV16");
	}
	else
	{
		jApi->set_json_codec_param_setting(jApi->Json_fmt, 0, (void *)"XV20");
	}
	set_video_fmt_setting(value);
	return 0;
}

int set_video_gdrmode_2_json(int value)
{
	bool gdr = false;
	if (value == gdrmode_false)
	{
		gdr = false;
		jApi->set_json_codec_param_setting(jApi->Json_gdrmode, 0, (void *)&gdr);
		
	}
	else
	{
		gdr = true;
		jApi->set_json_codec_param_setting(jApi->Json_gdrmode, 0, (void *)&gdr);
	}
	set_video_gdrmode_setting(value);
	return 0;
}

int set_video_gop_2_json(int value)
{
	jApi->set_json_codec_param_setting(jApi->Json_gop, 0, (void *)&value);
	set_video_gop_setting(value);
	return 0;
}

int set_video_mode_2_json(int value)
{
	if (value == mode_h264)
	{
		jApi->set_json_codec_param_setting(jApi->Json_vcu_mode, 0, (void *)"H264");
	}
	else
	{
		jApi->set_json_codec_param_setting(jApi->Json_vcu_mode, 0, (void *)"H265");
	}
	set_video_mode_setting(value);
	return 0;
}

int set_video_framerate_2_json(int value)
{
	jApi->set_json_codec_param_setting(jApi->Json_framerate, 0, (void *)&value);
	set_video_framerate_setting(value);
	return 0;
}

int set_video_height_2_json(int value)
{
	jApi->set_json_codec_param_setting(jApi->Json_videoHeight, 0, (void *)&value);
	set_video_height_setting(value);
	return 0;
}

int set_video_width_2_json(int value)
{
	jApi->set_json_codec_param_setting(jApi->Json_videoWidth, 0, (void *)&value);
	set_video_width_setting(value);
	return 0;
}

int set_audioswitch_2_json(int value)
{
	//jApi->set_json_codec_param_setting(jApi->Json_videoWidth, 0, (void *)&value);
	set_decoder_audioswitch_setting(value);
	return 0;
}
// -------------------------------
void jApi_t::printCodecInfo(int id)
{
    QJsonObject cmd, ret;

    cmd.insert("cmd", "getCodec");
    cmd.insert("id", id);
    ret = jApi->sendCmd(cmd);

    /* 返回的 json数据结构如下, 如果id为-1时，列出所有codec配置   id 不为-1 则codecList数组中只有一个与id对应的对象
    {
        "cmd":"codecCf10000g",
        "codecList":[
            {
                "id":0,
                "fmt":"NV12",
                "bitRate": ,
                ...
            },                  
            {
                "id":1,
                "fmt":"NV16",
                "bitRate": 10000,
                ...
            }
        ]
    }
    */

    QJsonArray codecList = ret.value("codecList").toArray(); // 从JSON中取 JSON数组方式

    if (0 >= codecList.count())
    {
        printf("Error: can't find codec! \n");
        return;
    }

    QJsonObject codecCfg = codecList.at(0).toObject(); // 从JSON数组中取其中一个元素

    int codecId = codecCfg.value("id").toInt(-1);                     // JSON 成员转 INT, 如果"id"这个成员不存在或不是int类型会失败，就按-1返回
	int rate = codecCfg.value("bitRate").toInt(-1);
    std::string fmt = codecCfg.value("fmt").toString().toStdString(); // JSON成员转 STD：：STRING,如果"fmt"这个成员不存在会失败，就按"XV20"返回
    bool gdrMode = codecCfg.value("gdrMode").toBool();                    // JSON 成员转 BOOL
	char *fmt_char = (char *)fmt.data();
	set_decoder_username_setting(fmt_char);
    printf("Codec id:%d  format is:%s gdr is %d bitrate %d\n", codecId, fmt.c_str(),gdrMode,rate);
}

bool jApi_t::setCodecRate(int id, int rate)
{
    QJsonObject cmd, ret;

    cmd.insert("cmd", "setCodec");
    cmd.insert("id", id);
    cmd.insert("bitRate", rate);
    ret = jApi->sendCmd(cmd);

    std::string tmpStr = ret.value("result").toString().toStdString();

    if ("success" != tmpStr)
        return false;
    else
        return true;
}

